package com.logstep;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

/*
 * 测步仪
 * */
public class StepMeter implements SensorEventListener {
    //存放三轴数据
    float[] oriValues = new float[3];
    final int ValueNum = 4;
    //用于存放计算阈值的波峰波谷差值
    float[] tempValue = new float[ValueNum];
    int tempCount = 0;
    //是否上升的标志位
    boolean isDirectionUp = false;
    //持续上升次数
    int continueUpCount = 0;
    //上一点的持续上升的次数，为了记录波峰的上升次数
    int continueUpFormerCount = 0;
    //上一点的状态，上升还是下降
    boolean lastStatus = false;
    //波峰值
    float peakOfWave = 0;
    //波谷值
    float valleyOfWave = 0;
    //此次波峰的时间
    long timeOfThisPeak = 0;
    //上次波峰的时间
    long timeOfLastPeak = 0;
    //当前的时间
    long timeOfNow = 0;
    //当前传感器的值
    float gravityNew = 0;
    //上次传感器的值
    float gravityOld = 0;
    //动态阈值需要动态的数据，这个值用于这些动态数据的阈值
    final float InitialValue = (float) 1.3;
    //初始阈值
    float ThreadValue = (float) 2.0;
    //波峰波谷时间差
    int TimeInterval = 500;
    private StepCountListener mStepListeners;
    private float[] accelerometerValues=new float[3];;
    private float[] magneticValues=new float[3];;

    //重力加速度 用来获取每一步最大和最小加速度用来测总体步长的
    private float oldBig=  9.8f;
    private float oldSmall=9.8f;
//    用来那个啥侧步长
    private boolean isUp;
    private float stepLength;
    //常数
    private float K=0.4f;
    @Override
    public void onSensorChanged(SensorEvent event) {
        mStepListeners.sensorValue(event);
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            accelerometerValues = event.values.clone();
            float[] R = new float[9];
            float[] values = new float[3];
            SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
            SensorManager.getOrientation(R, values);
            int degree = (int) Math.toDegrees(values[0]);//旋转角度
            if (degree < 0) {
                degree += 360;
            }
            mStepListeners.direction(degree);//获取到方向回去
            oriValues[0] = event.values[0];
            oriValues[1] = event.values[1];
            oriValues[2] = event.values[2];
            gravityNew = (float) Math.sqrt(oriValues[0] * oriValues[0] + oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);
            detectorNewStep(gravityNew);
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magneticValues = event.values.clone();
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    public void initListener(StepCountListener listener) {//给UI的
        this.mStepListeners = listener;
    }
    /*
     * 检测步子，并开始计步
     * 1.传入sersor中的数据
     * 2.如果检测到了波峰，并且符合时间差以及阈值的条件，则判定为1步
     * 3.符合时间差条件，波峰波谷差值大于initialValue，则将该差值纳入阈值的计算中
     * */
    public void detectorNewStep(float values) {
        if (gravityOld == 0) {
            gravityOld = values;
        } else {
            if (detectorPeak(values, gravityOld)) {
                timeOfLastPeak = timeOfThisPeak;
                timeOfNow = System.currentTimeMillis();
                if (timeOfNow - timeOfLastPeak >= TimeInterval && (peakOfWave - valleyOfWave >= ThreadValue)) {
                    timeOfThisPeak = timeOfNow;

                    isUp=false;
                    //完毕
//                    Log.i("emmmmmm最大加速度",String.valueOf(oldBig));
//                    Log.i("emmmmmm最小加速度",String.valueOf(oldSmall));

                    stepLength= (float) (K*Math.sqrt(Math.sqrt(oldBig-oldSmall)));
//                    Log.i("emmmmmm步长",String.valueOf(stepLength));

                    oldSmall=9.8f;
                    oldBig=9.8f;
                    mStepListeners.countStep(stepLength);
                }
                if (timeOfNow - timeOfLastPeak >= TimeInterval && (peakOfWave - valleyOfWave >= InitialValue)) {
                    timeOfThisPeak = timeOfNow;
                    ThreadValue = peakValleyThread(peakOfWave - valleyOfWave);
                }
            }

            if (isUp){
                if (values>oldBig){
                    oldBig=values;
                }
                if (values<oldSmall){
                    oldSmall=values;
                }
            }

        }
        gravityOld = values;
    }
    /*
     * 检测波峰
     * 以下四个条件判断为波峰：
     * 1.目前点为下降的趋势：isDirectionUp为false
     * 2.之前的点为上升的趋势：lastStatus为true
     * 3.到波峰为止，持续上升大于等于2次
     * 4.波峰值大于20
     * 记录波谷值
     * 1.观察波形图，可以发现在出现步子的地方，波谷的下一个就是波峰，有比较明显的特征以及差值
     * 2.所以要记录每次的波谷值，为了和下次的波峰做对比
     * */
    public boolean detectorPeak(float newValue, float oldValue) {
        lastStatus = isDirectionUp;
        if (newValue >= oldValue) {
            isDirectionUp = true;
            continueUpCount++;
        } else {
            continueUpFormerCount = continueUpCount;
            continueUpCount = 0;
            isDirectionUp = false;
        }
        if (!isDirectionUp && lastStatus && (continueUpFormerCount >= 2 || oldValue >= 20)) {
            peakOfWave = oldValue;
            return true;
        } else if (!lastStatus && isDirectionUp) {
            valleyOfWave = oldValue;
//            从波谷到波峰是第一个向上
            isUp=true;
//            Log.i("emmmmmm","向上");
//            Log.i("emmmmmm","波谷,有很多个");
            return false;
        } else {
//            Log.i("emmmmmmELSE","否则");
            return false;
        }
    }
    /*
     * 阈值的计算
     * 1.通过波峰波谷的差值计算阈值
     * 2.记录4个值，存入tempValue[]数组中
     * 3.在将数组传入函数averageValue中计算阈值
     * */
    public float peakValleyThread(float value) {
        float emmm = ThreadValue;
        if (tempCount < ValueNum) {
            tempValue[tempCount] = value;
            tempCount++;
        } else {
            emmm = averageValue(tempValue, ValueNum);
            for (int i = 1; i < ValueNum; i++) {
                tempValue[i - 1] = tempValue[i];
            }
            tempValue[ValueNum - 1] = value;
        }
        return emmm;

    }
    /*
     * 梯度化阈值
     * 1.计算数组的均值
     * 2.通过均值将阈值梯度化在一个范围里
     * */
    public float averageValue(float value[], int n) {
        float emm = 0;
        for (int i = 0; i < n; i++) {
            emm += value[i];
        }
        emm = emm / ValueNum;
        if (emm >= 8)
            emm = (float) 4.3;
        else if (emm >= 7 && emm < 8)
            emm = (float) 3.3;
        else if (emm >= 4 && emm < 7)
            emm = (float) 2.3;
        else if (emm >= 3 && emm < 4)
            emm = (float) 2.0;
        else {
            emm = (float) 1.3;
        }
        return emm;
    }

}
